﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.Xml;
using System.ComponentModel;
using SpeakupBackend.Classes;
using TableParsers;

namespace SpeakupBackend.Themes
{
    [Serializable]
    public sealed partial class BusinessTheme : IXmlSerializable,
                                IEquatable<BusinessTheme>,
                                IComparable,
                                IComparable<BusinessTheme>,
                                INotifyPropertyChanged,
                                ITheme
    {
        public BusinessTheme(BusinessLevelGroup levelGroup, Week week, String name)
        {
            this.m_levelGroup = levelGroup;
            this.m_week = week;
            this.m_name = name;
        }

        Week m_week;
        public Week Week
        {
            get
            {
                return m_week;
            }
        }

        BusinessLevelGroup m_levelGroup;
        public BusinessLevelGroup LevelGroup
        {
            get
            {
                return m_levelGroup;
            }
        }

        String m_name;
        public String Name
        {
            get
            {
                return m_name;
            }
            set
            {
                if (m_name != value)
                {
                    m_name = value;
                    OnPropertyChanged("Name");
                }
            }
        }

        public override string ToString()
        {
            return String.Format("Week: {0,2} | Level: {1,5} | Class: {2,10} | {3}",
                Week,
                LevelGroup,
                ClassType.Business,
                Name);
        }

        public override bool Equals(object obj)
        {
            return Equals(obj as BusinessTheme);
        }

        public bool Equals(BusinessTheme other)
        {
            return ClassHelper.IEquatableEquals(this, other);
        }

        public override int GetHashCode()
        {
            return ClassHelper.GetHashCode(LevelGroup, Week);
        }

        public int CompareTo(object obj)
        {
            return CompareTo((BusinessTheme)obj);
        }

        public int CompareTo(BusinessTheme other)
        {         
            if (LevelGroup != other.LevelGroup)
            {
                return LevelGroup.CompareTo(other.LevelGroup);
            }

            return Week.CompareTo(other.Week);
        }

        #region Comparison operators

        static public bool operator ==(BusinessTheme rhs, BusinessTheme lhs)
        {
            return ClassHelper.OperatorEqual(rhs, lhs);
        }

        static public bool operator !=(BusinessTheme rhs, BusinessTheme lhs)
        {
            return ClassHelper.OperatorNotEqual(rhs, lhs);
        }

        static public bool operator >(BusinessTheme rhs, BusinessTheme lhs)
        {
            return rhs.CompareTo(lhs) > 0;
        }

        static public bool operator <(BusinessTheme rhs, BusinessTheme lhs)
        {
            return rhs.CompareTo(lhs) < 0;
        }

        static public bool operator >=(BusinessTheme rhs, BusinessTheme lhs)
        {
            return rhs.CompareTo(lhs) >= 0;
        }

        static public bool operator <=(BusinessTheme rhs, BusinessTheme lhs)
        {
            return rhs.CompareTo(lhs) <= 0;
        }

        #endregion
    }

    /// <summary>
    /// xml serialization/deserelization
    /// </summary>
    public sealed partial class BusinessTheme
    {
        internal BusinessTheme()
        {
            //for xml deserialization
        }

        private static readonly string WeekAttributeName = "week";
        private static readonly string LevelAttributeName = "levelGroup";        

        public XmlSchema GetSchema()
        {
            throw new NotImplementedException();
        }

        public void ReadXml(XmlReader reader)
        {
            
            string levelValue = reader.GetAttribute(LevelAttributeName);
            if (levelValue == null)
            {
                throw new FormatException(String.Format("BusinessTheme element: Required attribute \"{0}\" is missing.", LevelAttributeName));
            }
            m_levelGroup = BusinessLevelGroup.BusinessFactory.GetLevelGroup(levelValue);

            string weekValue = reader.GetAttribute(WeekAttributeName);
            if (weekValue == null)
            {
                throw new FormatException(String.Format("BusinessTheme element: Required attribute \"{0}\" is missing.", WeekAttributeName));
            }
            m_week = Week.GetWeek(weekValue);

            Name = reader.ReadString();

            reader.ReadEndElement();
        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteAttributeString(LevelAttributeName, LevelGroup.ToString());
            writer.WriteAttributeString(WeekAttributeName, Week.ToString());
            writer.WriteString(Name);
        }
    }

    /// <summary>
    /// BusinessTheme Attended property
    /// </summary>
    public sealed partial class BusinessTheme : ThemeBase
    {
        public override bool IsCompatibleClass(Class cl)
        {
            if(ClassType.Business == cl.Name.Type)
            {

                Week clWeek = Week.GetWeek(cl.Time.Date);
                if (Week == clWeek)
                {
                    /* NOTE: business classes contain level number in their unit value. No need to translate from units to level */

                    if (!Level.IsValidLevelNumber(cl.Unit))
                    {
                        return false;
                    }

                    Level clLevel = Level.GetLevel(cl.Unit);
                    bool contains = LevelGroup.ContainsLevel(clLevel);
                    return contains;
                }
            }

            return false;
        }
    }
}
